package oneapm

import (
	"errors"
	"net/url"
	"strconv"
	"strings"

	"google.golang.org/protobuf/proto"

	"go.opentelemetry.io/collector/pkg/translator/oneapm/internal"

	"go.opentelemetry.io/collector/model/pdata"

	oneProto "go.opentelemetry.io/collector/pkg/translator/oneapm/proto"

	jsonIter "github.com/json-iterator/go"
)

const MsToNs = 1000000

// OneTransactionToTraces transaction接口数据转ot trace格式；contentType: "application/x-protobuf" | "application/json"
func OneTransactionToTraces(body []byte, contentType string) (pdata.Traces, error) {
	var transData oneProto.TransactionDataRequest
	var err error
	if strings.Contains(contentType, jsonContentType) {
		json := jsonIter.ConfigCompatibleWithStandardLibrary
		err = json.Unmarshal(body, &transData)
	} else if strings.Contains(contentType, pbContentType) {
		err = proto.Unmarshal(body, &transData)
	} else {
		err = errors.New("unSupport data format")
	}
	td := pdata.NewTraces()
	if err != nil {
		loggerOneApm.Debug("body", body)
		return td, err
	}
	if transData.GetTransactionInfo() == nil {
		return td, errors.New("incorrect request parameter format")
	}
	resourceSpansSlice := td.ResourceSpans()
	err = formatOTTrace(&transData, &resourceSpansSlice)
	if err != nil {
		return td, err
	}
	return td, nil
}

// OneTransactionsToTraces Transactions接口数据转ot trace格式；contentType: "application/x-protobuf" | "application/json"
func OneTransactionsToTraces(body []byte, contentType string) (pdata.Traces, error) {
	var transData oneProto.TransactionDatasRequest
	var err error
	if strings.Contains(contentType, jsonContentType) {
		json := jsonIter.ConfigCompatibleWithStandardLibrary
		err = json.Unmarshal(body, &transData)
	} else if strings.Contains(contentType, pbContentType) {
		err = proto.Unmarshal(body, &transData)
	} else {
		err = errors.New("unSupport data format")
	}
	td := pdata.NewTraces()
	if err != nil {
		loggerOneApm.Debug("body", body)
		return td, err
	}
	if transData.TransactionInfos == nil {
		return td, errors.New("incorrect request parameter format")
	}

	resourceSpansSlice := td.ResourceSpans()
	for _, info := range transData.TransactionInfos {
		var transDataItem oneProto.TransactionDataRequest
		transDataItem.Identifier = transData.GetIdentifier()
		transDataItem.TierName = transData.GetTierName()
		transDataItem.SettingHashCode = transData.GetSettingHashCode()
		transDataItem.TransactionInfo = info
		transDataItem.Resource = transData.Resource
		err = formatOTTrace(&transDataItem, &resourceSpansSlice)
		if err != nil {
			loggerOneApm.Error("format ot trace error", err)
			continue
		}
	}
	if err != nil {
		return td, err
	}
	return td, nil
}

func formatOTTrace(transData *oneProto.TransactionDataRequest, resourceSpansSlice *pdata.ResourceSpansSlice) error {
	resourceSpans := resourceSpansSlice.AppendEmpty()
	resource := resourceSpans.Resource()
	attributes := resource.Attributes()
	insertIdentifierAttribute(transData.GetResource(), transData.GetIdentifier(), &attributes)
	instrumentationLibrarySpansSlice := resourceSpans.InstrumentationLibrarySpans()
	instrumentationLibrarySpans := instrumentationLibrarySpansSlice.AppendEmpty()
	spanSlice := instrumentationLibrarySpans.Spans()

	// 生成spanID, 并记录id、spanID的关系，为了给下面parentId使用
	idSpanIDRealtion := make(map[int32][8]byte, len(transData.GetTransactionInfo().GetSpans()))
	spanIDTime := make(map[int32]uint64, len(transData.GetTransactionInfo().GetSpans()))
	for _, spanInfo := range transData.GetTransactionInfo().GetSpans() {
		_, spanID := internal.NewIDs()
		idSpanIDRealtion[spanInfo.GetSpanId()] = spanID
		spanIDTime[spanInfo.GetSpanId()] = uint64(transData.GetTransactionInfo().GetStartTimeMs()*1000000 + spanInfo.GetStartTimeNs())
	}
	spanParent := spanSlice.AppendEmpty()
	var err error
	spanParent, err = getParentSpan(spanParent, transData, spanIDTime)
	if err != nil {
		return err
	}
	spanSlice = getChildSpan(spanParent, spanSlice, transData, idSpanIDRealtion)
	return nil
}

func insertIdentifierAttribute(resource *oneProto.Resource, identifier string, attributes *pdata.AttributeMap) {
	if identifier != "" {
		attributes.InsertString("service.instance.id", identifier)
	}
	if resource.GetDataToken() != "" {
		attributes.InsertString("bk.data.token", resource.GetDataToken())
	}
	if resource.GetSdkLanguage() != "" {
		attributes.InsertString("telemetry.sdk.language", resource.GetSdkLanguage())
	}
	if resource.GetDataId() != "" {
		attributes.InsertString("bk.app.id", resource.GetDataId())
	}
	if resource.GetServiceName() != "" {
		attributes.InsertString("service.name", resource.GetServiceName())
	}
	if resource.GetHostIp() != "" {
		attributes.InsertString("net.host.ip", resource.GetHostIp())
	}
	if resource.GetHostName() != "" {
		attributes.InsertString("net.host.name", resource.GetHostName())
	}
	if resource.GetHostPort() != "" {
		portInt, err := strconv.ParseInt(resource.GetHostPort(), 10, 64)
		if err != nil {
			loggerOneApm.Error("strconv.Atoi error", err)
		} else {
			attributes.InsertInt("net.host.port", portInt)
		}
	}
}

func getParentSpan(span pdata.Span, transData *oneProto.TransactionDataRequest, spanIDTime map[int32]uint64) (pdata.Span, error) {
	traceID, err := internal.GetTraceIDFromOneapm(transData.GetTransactionInfo().GetTripId())
	if nil != err {
		loggerOneApm.Error("get traceID error:", err)
		return span, err
	}
	span.SetTraceID(pdata.NewTraceID(traceID))
	span.SetName(transData.GetTransactionInfo().GetTransactionName())
	if transData.GetTransactionInfo().GetTraceId() != "" {
		spanID, _ := internal.GetSpanIDFromOneapm(transData.GetTransactionInfo().GetTraceId())
		span.SetSpanID(pdata.NewSpanID(spanID))
	}
	if transData.GetTransactionInfo().GetRefTraceId() != "" {
		var parentID [8]byte
		parentID, _ = internal.GetSpanIDFromOneapm(transData.GetTransactionInfo().GetRefTraceId())
		span.SetParentSpanID(pdata.NewSpanID(parentID))
	}
	//java 纳秒时间调用的是System.nanoTime()，不是真正的纳秒时间戳
	var startNs int64
	var endNs int64
	if strings.Contains(strings.ToLower(transData.GetResource().GetSdkLanguage()), "java") {
		startNs = transData.GetTransactionInfo().GetStartTimeMs()*MsToNs + transData.GetTransactionInfo().GetStartTimeNs()%MsToNs
		endNs = transData.GetTransactionInfo().GetEndTimeMs()*MsToNs + transData.GetTransactionInfo().GetEndTimeNs()%MsToNs
	} else { //其余语言传的是纳秒时间戳
		startNs = transData.GetTransactionInfo().GetStartTimeNs()
		endNs = transData.GetTransactionInfo().GetEndTimeNs()
	}
	span.SetStartTimestamp(pdata.Timestamp(uint64(startNs)))
	span.SetEndTimestamp(pdata.Timestamp(uint64(endNs)))
	spanStatus := span.Status()
	spanStatus.SetMessage(transData.GetTransactionInfo().GetResponseMsg())
	var statusCode pdata.StatusCode
	if transData.GetTransactionInfo().GetResponseStatus() >= 400 {
		statusCode = pdata.StatusCodeError
	} else {
		statusCode = pdata.StatusCodeOk
	}
	spanStatus.SetCode(statusCode)
	spanEventSlice := span.Events() // 错误的放到event里
	for index, value := range transData.GetTransactionInfo().GetDataContext().GetErrorInfo() {
		spanEvent := spanEventSlice.AppendEmpty()
		spanEvent.SetName(value.GetMetricName())
		if _, ok := spanIDTime[value.GetSpanId()]; ok {
			spanEvent.SetTimestamp(pdata.Timestamp(spanIDTime[value.GetSpanId()]))
		}
		attributeMap := spanEvent.Attributes()
		if value.GetMsg() != "" {
			attributeMap.InsertString("exception.message", value.GetMsg())
		}
		if len(value.GetStacks()) > 0 {
			anyValue := pdata.NewAttributeValueArray()
			slices := anyValue.SliceVal()
			for _, stack := range value.GetStacks() {
				slice := slices.AppendEmpty()
				slice.SetStringVal(stack)
			}
			attributeMap.Insert("exception.stacktrace", anyValue)
		}
		if value.GetExceptionClass() != "" {
			attributeMap.InsertString("exception.type", value.GetExceptionClass())
		}
		if index == 0 { // 自定义参数
			for _, value := range transData.GetTransactionInfo().GetDataContext().GetErrorAttributes() {
				attributeMap.InsertString("exception.user.attr."+value.GetKey(), value.GetValue())
			}
		}
	}
	attribute := span.Attributes()
	if transData.GetTransactionInfo().GetThreadId() > 0 {
		attribute.InsertInt("thread.id", transData.GetTransactionInfo().GetThreadId())
	}
	if transData.GetTransactionInfo().GetThreadName() != "" {
		attribute.InsertString("thread.name", transData.GetTransactionInfo().GetThreadName())
	}
	if int64(transData.GetTransactionInfo().GetResponseStatus()) > 0 {
		attribute.InsertInt("http.status_code", int64(transData.GetTransactionInfo().GetResponseStatus()))
	}
	var parseURL string
	if transData.GetTransactionInfo().GetRequestUrl() != "" {
		attribute.InsertString("http.url", transData.GetTransactionInfo().GetRequestUrl())
		parseURL = transData.GetTransactionInfo().GetRequestUrl()
	}
	for _, value := range transData.GetTransactionInfo().GetDataContext().GetAgentAttributes() {
		if value.GetValue() != "" {
			attribute.Delete(value.GetKey())
			// net.peer.port | net.host.port | rpc.grpc.status_code | http.status_code | http.request_content_length | http.response_content_length | messaging.message_payload_size_bytes
			if value.GetKey() == "net.peer.port" || value.GetKey() == "net.host.port" || value.GetKey() == "rpc.grpc.status_code" || value.GetKey() == "http.status_code" || value.GetKey() == "http.request_content_length" || value.GetKey() == "http.response_content_length" || value.GetKey() == "messaging.message_payload_size_bytes" && value.GetValue() != "" {
				valueInt, err := strconv.ParseInt(value.GetValue(), 10, 64)
				if err != nil {
					loggerOneApm.Error("strconv.ParseInt error", err)
				} else {
					attribute.InsertInt(value.GetKey(), valueInt)
				}
			} else {
				if value.GetValue() != "" {
					attribute.InsertString(value.GetKey(), value.GetValue())
				}
			}
			if value.GetKey() == "http.url" {
				parseURL = value.GetValue()
			}
		}
	}
	if parseURL != "" {
		arr, err := url.Parse(parseURL)
		if err != nil {
			loggerOneApm.Error("url parse error", err)
		} else {
			if arr.Path != "" {
				attribute.InsertString("http.target", arr.Path)
			}
			if arr.Scheme != "" {
				attribute.InsertString("http.scheme", arr.Scheme)
			}
		}
	}
	// 自定义参数
	for _, item := range transData.GetTransactionInfo().GetDataContext().GetRequestParameters() {
		attribute.InsertString(item.GetKey(), item.GetValue())
	}
	PrefixedAgentAttributes := transData.GetTransactionInfo().GetDataContext().GetPrefixedAgentAttributes()
	for _, item := range PrefixedAgentAttributes.GetValue() {
		attribute.InsertString(PrefixedAgentAttributes.GetKey()+item.GetKey(), item.GetValue())
	}
	//如果是rpc，删除http的属性
	if _, has := attribute.Get("rpc.system"); has {
		attribute.Delete("http.url")
		attribute.Delete("http.scheme")
		attribute.Delete("http.target")
	}
	span.SetKind(pdata.SpanKindServer)
	return span, nil
}

func getChildSpan(spanParent pdata.Span, slice pdata.SpanSlice, transData *oneProto.TransactionDataRequest, idSpanIDRealtion map[int32][8]byte) pdata.SpanSlice {
	for _, spanInfo := range transData.GetTransactionInfo().GetSpans() {
		span := slice.AppendEmpty()
		span.SetTraceID(spanParent.TraceID())
		span.SetParentSpanID(spanParent.SpanID())                      //先设置为父
		if _, ok := idSpanIDRealtion[spanInfo.GetParentSpanId()]; ok { //如果有关联关系
			if spanInfo.GetParentSpanId() != spanInfo.GetSpanId() { //并且父不等于自己
				span.SetParentSpanID(pdata.NewSpanID(idSpanIDRealtion[spanInfo.GetParentSpanId()])) //则设置关联关系
			}
		}
		if _, ok := idSpanIDRealtion[spanInfo.GetSpanId()]; ok {
			span.SetSpanID(pdata.NewSpanID(idSpanIDRealtion[spanInfo.GetSpanId()]))
		}
		//java 纳秒时间调用的是System.nanoTime()，不是真正的纳秒时间戳
		var startNs int64
		var endNs int64
		//子spans是相对父span的startTime的时间
		if strings.Contains(strings.ToLower(transData.GetResource().GetSdkLanguage()), "java") {
			startNs = transData.GetTransactionInfo().GetStartTimeMs()*MsToNs + transData.GetTransactionInfo().GetStartTimeNs()%MsToNs + spanInfo.GetStartTimeNs()
			endNs = transData.GetTransactionInfo().GetStartTimeMs()*MsToNs + transData.GetTransactionInfo().GetStartTimeNs()%MsToNs + spanInfo.GetStopTimeNs()
		} else { //其余语言传的是纳秒时间戳
			startNs = transData.GetTransactionInfo().GetStartTimeNs() + spanInfo.GetStartTimeNs()
			endNs = transData.GetTransactionInfo().GetStartTimeNs() + spanInfo.GetStopTimeNs()
		}
		span.SetStartTimestamp(pdata.Timestamp(uint64(startNs)))
		span.SetEndTimestamp(pdata.Timestamp(uint64(endNs)))
		metricName := internal.GetCommonMetricName(spanInfo, transData, cache)
		span.SetName(metricName)
		spanStatus := span.Status()
		spanStatus.SetCode(spanParent.Status().Code())
		spanStatus.SetMessage(spanParent.Status().Message())

		attribute := span.Attributes()
		switch spanInfo.GetType() {
		case 1, 3:
			span.SetKind(pdata.SpanKindClient)
			setDataAccessAttr(attribute, spanInfo, metricName, transData)
		case 2:
			span.SetKind(pdata.SpanKindClient)
			if spanInfo.GetExternal().GetSpanRefTraceid() != "" {
				spanID, err := internal.GetSpanIDFromOneapm(spanInfo.GetExternal().GetSpanRefTraceid())
				if err != nil {
					loggerOneApm.Error("get spanId error", err)
				}
				span.SetSpanID(pdata.NewSpanID(spanID))
			}
			setExternalAttr(attribute, spanInfo, transData)
		case 4:
			if internal.MQDestType[spanInfo.GetMq().GetDestType()] == "Produce" {
				span.SetKind(pdata.SpanKindProducer)
			} else {
				span.SetKind(pdata.SpanKindConsumer)
			}
			setMessageAttr(attribute, spanInfo)
		case 5:
			span.SetKind(pdata.SpanKindInternal)
			setOtherAttr(attribute, spanInfo)
		}
		for _, value := range spanInfo.GetAgentAttributes() {
			if value.GetValue() != "" {
				attribute.Delete(value.GetKey())
				// net.peer.port | net.host.port | rpc.grpc.status_code | http.status_code | http.request_content_length | http.response_content_length | messaging.message_payload_size_bytes
				if value.GetKey() == "net.peer.port" || value.GetKey() == "net.host.port" || value.GetKey() == "rpc.grpc.status_code" || value.GetKey() == "http.status_code" || value.GetKey() == "http.request_content_length" || value.GetKey() == "http.response_content_length" || value.GetKey() == "messaging.message_payload_size_bytes" || value.GetKey() == "code.lineno" {
					valueInt, err := strconv.ParseInt(value.GetValue(), 10, 64)
					if err != nil {
						loggerOneApm.Error("strconv.ParseInt error", err)
					} else {
						attribute.InsertInt(value.GetKey(), valueInt)
					}
				} else {
					attribute.InsertString(value.GetKey(), value.GetValue())
				}
				if value.GetKey() == "http.url" {
					arr, err := url.Parse(value.GetValue())
					if err != nil {
						loggerOneApm.Error("url parse error", err)
					} else {
						if arr.Path != "" {
							attribute.InsertString("http.target", arr.Path)
						}
						if arr.Scheme != "" {
							attribute.InsertString("http.scheme", arr.Scheme)
						}
						if arr.Port() != "" {
							portInt, _ := strconv.ParseInt(arr.Port(), 10, 64)
							if portInt > 0 {
								attribute.InsertInt("net.peer.port", portInt)
							}
						}
					}
				}
				if value.GetKey() == "messaging.destination_type" {
					attribute.Delete(value.GetKey()) // 和span.kind重复了，不需要设置
				}
			}
		}
	}
	return slice
}

func setDataAccessAttr(attribute pdata.AttributeMap, spanInfo *oneProto.SpanInfo, metricName string, transData *oneProto.TransactionDataRequest) {
	if _, ok := internal.KindInfo[spanInfo.GetKind()]; !ok {
		return
	}
	system := internal.KindInfo[spanInfo.GetKind()]["ot"]
	attribute.InsertString("db.system", system)
	var host, operate string
	var portInt int64
	metricNameArr := strings.Split(metricName, "/")
	if len(metricNameArr) >= 3 {
		hostPortArr := strings.Split(metricNameArr[2], ":")
		if len(hostPortArr) == 3 {
			host = hostPortArr[1]
			var err error
			if hostPortArr[2] != "" {
				portInt, err = strconv.ParseInt(hostPortArr[2], 10, 64)
				if err != nil {
					loggerOneApm.Error("strconv.ParseInt error", err)
				}
			}
		}
	}
	if len(metricNameArr) == 5 { // Mongodb、Cassandra、InfluxDB
		attribute.InsertString("db.sql.table", metricNameArr[3])
		operate = metricNameArr[4]
		if internal.KindInfo[spanInfo.GetKind()]["oneapm"] == "InfluxDB" {
			if spanInfo.GetInfluxDBSpanInfo().GetSql() != "" {
				attribute.InsertString("db.statement", spanInfo.GetInfluxDBSpanInfo().GetSql())
			}
		} else if internal.KindInfo[spanInfo.GetKind()]["oneapm"] == "Cassandra" {
			if spanInfo.GetCassandraSpanInfo().GetSql() != "" {
				attribute.InsertString("db.statement", spanInfo.GetCassandraSpanInfo().GetSql())
			}
			attribute.Delete("db.sql.table")
			attribute.InsertString("db.cassandra.table", metricNameArr[3])
		} else if internal.KindInfo[spanInfo.GetKind()]["oneapm"] == "MongoDB" {
			if spanInfo.GetMongodbSpanInfo().GetDborcoll() != "" {
				attribute.InsertString("db.mongodb.collection", spanInfo.GetMongodbSpanInfo().GetDborcoll())
			}
		}
	} else if len(metricNameArr) == 4 { // Redis、Memcached
		operate = metricNameArr[3]
		if internal.KindInfo[spanInfo.GetKind()]["oneapm"] == "spymemcached" {
			if spanInfo.GetSpymemcachedSpanInfo().GetSqlInfo() != "" {
				attribute.InsertString("db.statement", spanInfo.GetSpymemcachedSpanInfo().GetSqlInfo())
			}
		} else if internal.KindInfo[spanInfo.GetKind()]["oneapm"] == "xMemcached" {
			if spanInfo.GetXmemcachedSpanInfo().GetSqlValue() != "" {
				attribute.InsertString("db.statement", spanInfo.GetXmemcachedSpanInfo().GetSqlValue())
			}
		} else if internal.KindInfo[spanInfo.GetKind()]["oneapm"] == "Memcached" {
			if spanInfo.GetMemcachedSpanInfo().GetSqlValue() != "" {
				attribute.InsertString("db.statement", spanInfo.GetMemcachedSpanInfo().GetSqlValue())
			}
		}
	} else if len(metricNameArr) == 6 { // database
		operate = metricNameArr[5]
		if metricNameArr[4] != "" {
			attribute.InsertString("db.sql.table", metricNameArr[4])
		}
		if metricNameArr[3] != "" {
			attribute.InsertString("db.name", metricNameArr[3])
		}
		if spanInfo.GetDatabaseSpanInfo().GetSql() != "" {
			attribute.InsertString("db.statement", spanInfo.GetDatabaseSpanInfo().GetSql())
		}
		connectionString := internal.GetHostFromIndex(spanInfo.GetDatabaseSpanInfo().GetUrl(), transData.GetTransactionInfo().GetDataContext().GetHostAndUrls())
		if connectionString == "" {
			connectionString = internal.GetHostFromIndex(spanInfo.GetDatabaseSpanInfo().GetUrlFromDataSource(), transData.GetTransactionInfo().GetDataContext().GetHostAndUrls())
		}
		if connectionString != "" {
			attribute.InsertString("db.connection_string", connectionString)
		}
	}
	if operate != "" {
		attribute.InsertString("db.operation", strings.ToUpper(operate))
	}
	if host != "" {
		attribute.InsertString("net.peer.name", host)
	}
	if portInt > 0 {
		attribute.InsertInt("net.peer.port", portInt)
	}
}

func setExternalAttr(attribute pdata.AttributeMap, spanInfo *oneProto.SpanInfo, transData *oneProto.TransactionDataRequest) {
	host := internal.GetHost(spanInfo.GetExternal().GetUrl(), spanInfo.GetExternal().GetHost(), transData.TransactionInfo.GetDataContext().HostAndUrls)
	if host != "" {
		attribute.InsertString("net.peer.name", host)
	}
	if spanInfo.GetExternal().GetPort() != "" {
		portInt, err := strconv.ParseInt(spanInfo.GetExternal().GetPort(), 10, 64)
		if err != nil {
			loggerOneApm.Error("strconv.ParseInt error:", err)
		}
		attribute.InsertInt("net.peer.port", portInt)
	}
	if _, ok := internal.KindInfo[spanInfo.GetKind()]; ok {
		otKind := internal.KindInfo[spanInfo.GetKind()]["ot"]
		if strings.Contains(otKind, "rpc") || otKind == "java_rmi" || otKind == "wcf" {
			attribute.InsertString("rpc.system", internal.KindInfo[spanInfo.GetKind()]["ot"])
		} else {
			if spanInfo.GetExternal().GetUrl() != "" {
				attribute.InsertString("http.url", spanInfo.GetExternal().GetUrl())
			}
			method := internal.GetMethod(spanInfo.GetExternal().GetMethod())
			if method != "" {
				attribute.InsertString("http.method", method)
			}
			if spanInfo.GetExternal().GetUrl() != "" {
				arr, err := url.Parse(spanInfo.GetExternal().GetUrl())
				if err != nil {
					loggerOneApm.Error("url parse error", err)
				} else {
					if arr.Path != "" {
						attribute.InsertString("http.target", arr.Path)
					}
					if arr.Scheme != "" {
						attribute.InsertString("http.scheme", arr.Scheme)
					}
					if arr.Port() != "" {
						portInt, _ := strconv.ParseInt(arr.Port(), 10, 64)
						if portInt > 0 {
							attribute.InsertInt("net.peer.port", portInt)
						}
					}
				}
			}
		}
	}
}

func setMessageAttr(attribute pdata.AttributeMap, spanInfo *oneProto.SpanInfo) {
	if _, ok := internal.KindInfo[spanInfo.GetKind()]; ok {
		attribute.InsertString("messaging.system", internal.KindInfo[spanInfo.GetKind()]["ot"])
	}
	if spanInfo.GetMq().GetDestName() != "" {
		attribute.InsertString("messaging.destination", spanInfo.GetMq().GetDestName())
	}
	if _, ok := internal.MQTypeInfo[spanInfo.GetMq().GetMqType()]; ok {
		attribute.InsertString("messaging.destination_kind", internal.MQTypeInfo[spanInfo.GetMq().GetMqType()])
	}
	if spanInfo.GetMq().GetMqType() == 3 || spanInfo.GetMq().GetMqType() == 4 {
		attribute.InsertBool("messaging.temp_destination", true)
	} else {
		attribute.InsertBool("messaging.temp_destination", false)
	}
}

func setOtherAttr(attribute pdata.AttributeMap, spanInfo *oneProto.SpanInfo) {
	if spanInfo.GetCommonMetricSpanInfo().GetMethodName() != "" {
		attribute.InsertString("code.function", spanInfo.GetCommonMetricSpanInfo().GetMethodName())
	} else {
		if spanInfo.GetMethodName() != "" {
			attribute.InsertString("code.function", spanInfo.GetMethodName())
		}
	}
	if spanInfo.GetCommonMetricSpanInfo().GetClassName() != "" {
		attribute.InsertString("code.namespace", spanInfo.GetCommonMetricSpanInfo().GetClassName())
	} else if spanInfo.GetClassName() != "" {
		attribute.InsertString("code.namespace", spanInfo.GetClassName())
	}
	if spanInfo.GetStartLineNum() > 0 {
		attribute.Delete("code.lineno")
		attribute.InsertInt("code.lineno", int64(spanInfo.GetStartLineNum()))
	}
}
